package shardkv

import "time"
import "6.824/shardctrler"

//
// Sharded key/value server.
// Lots of replica groups, each running Raft.
// Shardctrler decides which group serves each shard.
// Shardctrler may change shard assignment from time to time.
//
// You will have to modify these definitions.
//

const PullConfigTimeout = 100 * time.Millisecond

const (
	OK              = "OK"
	ErrNoKey        = "ErrNoKey"
	ErrWrongGroup   = "ErrWrongGroup"
	ErrWrongLeader  = "ErrWrongLeader"
	ErrDuplicate    = "ErrDuplicate"
	ErrConfigAhead  = "ErrConfigAhead"
	ErrConfigBehind = "ErrConfigBehind"
)

type Err string

//提交配置信息
type ConfigCommand struct {
	PrevConfig shardctrler.Config
	CurConfig  shardctrler.Config
}

//操作切片数据库的
type OpCommand struct {
	Type  string
	Key   string
	Value string

	ClientId int64
	CmdId    int64
}

type ShardCommand struct {
	Type         string
	Shard        *Shard
	Sid          int
	ConfigNum    int
	ClientCmdSeq map[int64]int64
}

//空命令用来同步日志
type EmptyCommand struct {
}

type ShardArgs struct {
	Type      string
	ShardId   int
	ConfigNum int
}

type ShardReply struct {
	Err          Err
	Shard        Shard
	ConfigNum    int
	ClientCmdSeq map[int64]int64
}

//用于缓存的正在处理的删除命令
type DeleteInfo struct {
	ch      chan *ShardReply
	command *ShardCommand
}

//操作命令给客户端的回复
type Reply struct {
	Err   Err
	Value string
}

const (
	//处理完，新数据或者彻底废弃的旧数据，此时若分片属于自己可以访问
	Ready int = iota
	//需要从其他分片获取信息,此时不可访问
	NeedPull
	//分片拉取完需要通知对方回收空间，此时已经可以访问
	NeedNotify
	//被拉取方状态，等待其他人拉取并通知自己回收
	Waiting
)

//切片的定义
type Shard struct {
	//存储的数据信息
	DB    map[string]string
	State int
}

// Put or Append
type PutAppendArgs struct {
	// You'll have to add definitions here.
	Key   string
	Value string
	Op    string // "Put" or "Append"
	// You'll have to add definitions here.
	// Field names must start with capital letters,
	// otherwise RPC will break.
	ClientId int64
	CmdId    int64
}

type PutAppendReply struct {
	Err Err
}

type GetArgs struct {
	Key string
	// You'll have to add definitions here.
	ClientId int64
	CmdId    int64
}

type GetReply struct {
	Err   Err
	Value string
}
